<script lang="ts" setup>
import type { SystemDeptApi } from '#/api/system/dept';
import type { SystemUserApi } from '#/api/system/user';

import { computed, nextTick, ref, watch } from 'vue';

import { useVbenModal } from '@vben/common-ui';
import { handleTree } from '@vben/utils';

import { Loading, OfficeBuilding, Search } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';

import { getDeptTree } from '#/api/system/dept';
import { getUserPage } from '#/api/system/user';

// 类型定义
interface UserQueryParams {
  pageNo: number;
  pageSize: number;
  username?: string;
  deptId?: number;
  userIds?: number[];
}

interface UserQueryResponse {
  list: SystemUserApi.User[];
  total: number;
}

interface DeptTreeNode {
  key: string;
  label: string;
  children?: DeptTreeNode[];
  name: string;
}

// 组件属性
defineOptions({ name: 'SelectUserModel' });

const props = withDefaults(
  defineProps<{
    cancelText?: string;
    confirmText?: string;
    multiple?: boolean;
    value?: number[];
  }>(),
  {
    multiple: true,
    value: () => [],
    confirmText: '确定',
    cancelText: '取消',
  },
);

// 事件定义
const emit = defineEmits<{
  cancel: [];
  closed: [];
  confirm: [value: SystemUserApi.User[]];
  'update:value': [value: number[]];
}>();

// 响应式数据
const deptList = ref<SystemDeptApi.Dept[]>([]);
const userList = ref<SystemUserApi.User[]>([]);
const selectedUserIds = ref<string[]>([]);
const selectedUsersMap = ref(new Map<string, SystemUserApi.User>());
const searchKeyword = ref('');
const searchDeptId = ref<number>();
const showSelectedDrawer = ref(false);
const currentPage = ref(1);
const pageSize = ref(20);
const totalUsers = ref(0);
const isSettingSelection = ref(false); // 防止循环更新的标志

// 模板引用
const userRef = ref();

// 用户查询状态管理
const queryState = ref({
  isLoading: false,
  currentParams: {
    pageNo: 1,
    pageSize: 20,
  } as UserQueryParams,
  queryMode: 'normal' as 'dept' | 'normal' | 'search',
});

// 计算属性
const tableHeight = computed(() => 'calc(100vh - 280px)');

const selectedUsers = computed(() =>
  [...selectedUsersMap.value.values()].filter((user) => user.id !== undefined),
);

const treeProps = computed(() => ({
  children: 'children',
  label: 'name',
}));

const deptTree = computed(() => {
  const treeData = handleTree(deptList.value);
  return treeData.map((node) => processDeptNode(node));
});

const rowKey = (row: SystemUserApi.User) => String(row.id);

// 方法定义
// 统一的用户查询方法
async function queryUsers(
  params?: Partial<UserQueryParams>,
): Promise<UserQueryResponse> {
  const queryParams: UserQueryParams = {
    ...queryState.value.currentParams,
    ...params,
  };

  queryState.value.currentParams = queryParams;
  queryState.value.isLoading = true;

  try {
    const response = await getUserPage(queryParams);

    // 更新查询模式
    if (params?.deptId !== undefined) {
      queryState.value.queryMode = 'dept';
    } else if (params?.username) {
      queryState.value.queryMode = 'search';
    } else {
      queryState.value.queryMode = 'normal';
    }

    return response;
  } catch (error) {
    console.error('查询用户失败:', error);
    ElMessage.error('查询用户失败');
    throw error;
  } finally {
    queryState.value.isLoading = false;
  }
}

// 初始查询
async function queryInitialUsers() {
  try {
    const { list, total } = await queryUsers({
      pageNo: 1,
      pageSize: pageSize.value,
    });

    userList.value = list;
    totalUsers.value = total;
    currentPage.value = 1;
  } catch {
    // 错误已在 queryUsers 中处理
  }
}

// 根据部门查询
async function queryUsersByDept() {
  try {
    const { list, total } = await queryUsers({
      pageNo: 1,
      deptId: searchDeptId.value,
      username: undefined,
    });

    userList.value = list;
    totalUsers.value = total;
    currentPage.value = 1;
    searchKeyword.value = '';

    ElMessage.success(`已加载该部门用户`);
  } catch {
    // 错误已在 queryUsers 中处理
  }
}

// 搜索用户
async function searchUsers() {
  try {
    const { list, total } = await queryUsers({
      pageNo: 1,
      username: searchKeyword.value || undefined,
      deptId: searchDeptId.value,
    });

    userList.value = list;
    totalUsers.value = total;
    currentPage.value = 1;

    if (searchKeyword.value) {
      ElMessage.success(`找到 ${total} 个相关用户`);
    }
  } catch {
    // 错误已在 queryUsers 中处理
  }
}

// 分页查询
async function queryUsersByPage(pageNo: number, newPageSize?: number) {
  try {
    const params: Partial<UserQueryParams> = { pageNo };
    if (newPageSize) {
      params.pageSize = newPageSize;
      pageSize.value = newPageSize;
    }

    const { list, total } = await queryUsers(params);

    userList.value = list;
    totalUsers.value = total;
    currentPage.value = pageNo;
  } catch {
    // 错误已在 queryUsers 中处理
  }
}

// 处理部门树节点
function processDeptNode(node: any): DeptTreeNode {
  return {
    key: String(node.id),
    label: `${node.name} (${node.id})`,
    name: node.name,
    children: node.children?.map((child: any) => processDeptNode(child)),
  };
}

// 部门选择处理
async function handleDeptSelect(nodeData: any) {
  // nodeData 包含部门的基本信息
  searchDeptId.value = nodeData.key;

  await queryUsersByDept();
}

// 分页处理
function handleSizeChange(newSize: number) {
  queryUsersByPage(1, newSize);
}

function handleCurrentChange(newPage: number) {
  queryUsersByPage(newPage);
}

// 表格选择处理 - 修改为支持跨页面保持选择
function handleSelectionChange(selection: SystemUserApi.User[]) {
  // 如果是正在设置选择状态，则跳过
  if (isSettingSelection.value) return;

  // 更新当前页面的选中状态
  const currentPageUserIds = userList.value.map((user) => String(user.id));

  // 移除当前页面不再选中的用户
  currentPageUserIds.forEach((userId) => {
    if (!selection.some((user) => String(user.id) === userId)) {
      selectedUsersMap.value.delete(userId);
    }
  });

  // 添加新选中的用户
  selection.forEach((user) => {
    selectedUsersMap.value.set(String(user.id), user);
  });

  // 更新选中ID列表
  selectedUserIds.value = [...selectedUsersMap.value.keys()];
}

// 设置表格选中状态
function setTableSelection() {
  if (!userRef.value || userList.value.length === 0) return;

  isSettingSelection.value = true;

  nextTick(() => {
    try {
      // 清除当前页面的选中状态
      userRef.value.clearSelection();

      // 设置当前页面中已选用户的选中状态
      userList.value.forEach((user) => {
        if (selectedUserIds.value.includes(String(user.id))) {
          userRef.value.toggleRowSelection(user, true);
        }
      });
    } catch (error) {
      console.error('设置表格选中状态失败:', error);
    } finally {
      // 使用 setTimeout 确保在下一个事件循环中重置标志
      setTimeout(() => {
        isSettingSelection.value = false;
      }, 0);
    }
  });
}

// 清空选择
function clearSelection() {
  selectedUsersMap.value.clear();
  selectedUserIds.value = [];
  // 清空表格选中状态
  if (userRef.value) {
    userRef.value.clearSelection();
  }
}

// 确认选择
function handleConfirm() {
  const selectedUsers = [...selectedUsersMap.value.values()].filter(
    (user) => user.id !== undefined,
  );

  if (selectedUsers.length === 0) {
    ElMessage.warning('请选择用户');
    return;
  }

  emit('confirm', selectedUsers);
  modalApi.close();
}

// 取消选择
function handleCancel() {
  emit('cancel');
  modalApi.close();
}

// 关闭弹窗
function handleClosed() {
  emit('closed');
  resetData();
}

// 重置数据
function resetData() {
  userList.value = [];
  selectedUserIds.value = [];
  selectedUsersMap.value.clear();
  searchKeyword.value = '';
  searchDeptId.value = undefined;
  currentPage.value = 1;
  totalUsers.value = 0;
  isSettingSelection.value = false;

  queryState.value = {
    isLoading: false,
    currentParams: {
      pageNo: 1,
      pageSize: 20,
    },
    queryMode: 'normal',
  };
}

// 初始化数据
async function initData(data: any) {
  modalApi.lock();
  try {
    // 加载部门数据
    const deptData = await getDeptTree();
    deptList.value = deptData;

    // 清空之前的选择
    selectedUsersMap.value.clear();

    // 设置已选用户
    if (data?.userIds?.length) {
      const userIds = data.userIds.map(String);
      selectedUserIds.value = userIds;

      // 预填充选中用户的Map，等待数据加载后补充完整信息
      userIds.forEach((userId: any) => {
        selectedUsersMap.value.set(userId, {} as SystemUserApi.User);
      });

      // 加载已选用户的完整信息
      const { list } = await queryUsers({
        pageNo: 1,
        pageSize: 100,
      });

      // 更新选中用户的完整信息
      list.forEach((user) => {
        if (selectedUsersMap.value.has(String(user.id))) {
          selectedUsersMap.value.set(String(user.id), user);
        }
      });

      userList.value = list;
      totalUsers.value = list.length;
    } else {
      // 初始查询
      await queryInitialUsers();
    }

    modalApi.open();
  } catch {
    ElMessage.error('初始化数据失败');
  } finally {
    modalApi.unlock();
  }
}

// 弹窗配置
const [Modal, modalApi] = useVbenModal({
  onCancel: handleCancel,
  onClosed: handleClosed,
  appendToMain: true,
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      resetData();
      return;
    }

    const data = modalApi.getData();
    await initData(data);
  },
  destroyOnClose: true,
});

// 监听用户列表变化，确保选择状态正确显示
watch(
  userList,
  () => {
    setTableSelection();
  },
  { immediate: true },
);

// 监听搜索关键词变化，添加防抖
let searchTimer: NodeJS.Timeout;
watch(searchKeyword, () => {
  clearTimeout(searchTimer);
  searchTimer = setTimeout(() => {
    searchUsers();
  }, 500);
});
</script>

<template>
  <!-- 使用单个根元素包裹 Modal 组件 -->
  <div class="select-user-modal">
    <Modal>
      <!-- 头部工具栏 -->
      <template #title>
        <div class="flex w-full items-center justify-between">
          <span class="text-lg font-semibold">{{ title }}</span>
          <div class="ml-auto mr-[80px] flex space-x-4">
            <!-- 查看已选按钮 -->
            <el-badge
              :value="selectedUserIds.length"
              :max="99"
              :hidden="selectedUserIds.length === 0"
            >
              <el-button
                @click="showSelectedDrawer = true"
                :disabled="selectedUserIds.length === 0"
              >
                已选用户
              </el-button>
            </el-badge>

            <el-input
              v-model="searchKeyword"
              placeholder="搜索用户名或昵称"
              clearable
              class="w-60"
              @clear="searchUsers"
            >
              <template #prefix>
                <el-icon><Search /></el-icon>
              </template>
            </el-input>
          </div>
        </div>
      </template>

      <!-- 主要内容区域 -->
      <div class="flex h-full flex-col">
        <div class="flex min-h-0 flex-1 gap-4">
          <!-- 左侧部门树 -->
          <div class="flex w-1/3 flex-col overflow-hidden rounded-lg border">
            <div class="border-b bg-gray-50 p-3 font-medium">部门列表</div>
            <div class="flex-1 overflow-auto">
              <ElTree
                :data="deptTree"
                :props="treeProps"
                node-key="key"
                :default-expand-all="true"
                :expand-on-click-node="false"
                :highlight-current="true"
                @node-click="handleDeptSelect"
                class="p-2"
              >
                <template #default="{ data }">
                  <span class="flex items-center">
                    <el-icon class="mr-1"><OfficeBuilding /></el-icon>
                    <span>{{ data.name }}</span>
                  </span>
                </template>
              </ElTree>
            </div>
          </div>

          <!-- 右侧用户列表 -->
          <div class="flex flex-1 flex-col overflow-hidden rounded-lg border">
            <div
              class="flex min-h-[44px] items-center justify-between border-b bg-gray-50 p-3 font-medium"
            >
              <span>用户列表</span>
              <div class="flex items-center space-x-2">
                <el-icon v-if="queryState.isLoading" class="is-loading">
                  <Loading />
                </el-icon>
                <span class="whitespace-nowrap text-sm text-gray-500">
                  已选择 {{ selectedUserIds.length }} 个用户
                </span>
                <el-button
                  type="primary"
                  text
                  size="small"
                  @click="clearSelection"
                  :class="[
                    selectedUserIds.length > 0
                      ? 'scale-100 opacity-100'
                      : 'pointer-events-none scale-95 opacity-0',
                  ]"
                >
                  清空选择
                </el-button>
              </div>
            </div>

            <div class="flex-1 overflow-hidden">
              <ElTable
                ref="userRef"
                :data="userList"
                :max-height="tableHeight"
                v-loading="queryState.isLoading"
                @selection-change="handleSelectionChange"
                :row-key="rowKey"
              >
                <el-table-column
                  type="selection"
                  width="55"
                  :reserve-selection="false"
                />
                <el-table-column prop="nickname" label="昵称" min-width="120">
                  <template #default="{ row }">
                    <div class="flex items-center">
                      <el-avatar :size="32" :src="row.avatar" class="mr-3">
                        {{ row.nickname?.charAt(0) || '' }}
                      </el-avatar>
                      <div>
                        <div class="font-medium">{{ row.nickname }}</div>
                        <div class="text-xs text-gray-500">{{ row.email }}</div>
                      </div>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column
                  prop="username"
                  label="用户名"
                  min-width="100"
                />
                <el-table-column prop="deptName" label="部门" min-width="120" />
                <el-table-column prop="mobile" label="手机号" min-width="120" />
                <el-table-column label="状态" width="80">
                  <template #default="{ row }">
                    <el-tag
                      :type="row.status === 0 ? 'success' : 'info'"
                      size="small"
                    >
                      {{ row.status === 0 ? '在职' : '离职' }}
                    </el-tag>
                  </template>
                </el-table-column>
              </ElTable>
            </div>

            <!-- 分页 -->
            <div
              class="flex items-center justify-between border-t bg-gray-50 p-3"
              v-if="totalUsers > 0"
            >
              <div class="text-sm text-gray-500">
                共 {{ totalUsers }} 个用户
              </div>
              <el-pagination
                v-model:current-page="currentPage"
                v-model:page-size="pageSize"
                :page-sizes="[10, 20, 50, 100]"
                :total="totalUsers"
                layout="sizes, prev, pager, next, jumper"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
              />
            </div>
          </div>
        </div>
      </div>

      <template #footer>
        <ElButton
          type="primary"
          :disabled="selectedUserIds.length === 0"
          @click="handleConfirm"
        >
          {{ confirmText }} ({{ selectedUserIds.length }})
        </ElButton>
        <ElButton @click="handleCancel">{{ cancelText }}</ElButton>
      </template>
    </Modal>

    <!-- 已选用户抽屉 -->
    <el-drawer
      v-model="showSelectedDrawer"
      title="已选用户"
      direction="rtl"
      size="400px"
    >
      <div class="p-4">
        <div class="mb-4 flex items-center justify-between">
          <span class="text-sm text-gray-500">
            已选择 {{ selectedUsers.length }} 个用户
          </span>
          <el-button type="primary" text size="small" @click="clearSelection">
            清空选择
          </el-button>
        </div>

        <div class="space-y-3">
          <div
            v-for="user in selectedUsers"
            :key="user.id"
            class="flex items-center rounded-lg border p-3"
          >
            <el-avatar :size="40" :src="user.avatar" class="mr-3">
              {{ user.nickname?.charAt(0) || '' }}
            </el-avatar>
            <div class="flex-1">
              <div class="font-medium">{{ user.nickname }}</div>
              <div class="text-sm text-gray-500">{{ user.username }}</div>
              <div class="text-xs text-gray-400">{{ user.deptName }}</div>
            </div>
          </div>
        </div>
      </div>
    </el-drawer>
  </div>
</template>

<style scoped>
.select-user-modal {
  /* 确保组件有单个根元素 */
}

:deep(.el-tree-node__content) {
  padding: 4px 0;
}

:deep(.el-tree-node.is-current > .el-tree-node__content) {
  color: #409eff;
  background-color: #ecf5ff;
}

.transition-all {
  transition: all 0.2s ease-in-out;
}
</style>
